package com.youhome.service.utils;



import com.youhome.service.model.Point;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by chen365 on 2018/07/09.
 */
public class GoogleMapUtils {

    private static final double EARTH_RADIUS = 6378137.0;

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 计算两坐标点距离(米)
     *
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return
     */
    public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
                Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        //s = s*1000;
        return s;
    }

//    public static void main(String[] args) {
//        //40.7520027161 lng:-74.002166748 lat1:40.751812 lng1:-74.00182
////         System.out.println(getDistance(29.490295,106.486654,29.615467,106.581515)+"米");
////         System.out.println(getDistance(-73.997232,40.674888,-73.983578,40.677405)+"米");
//
//        System.out.println(getDistance(29.490295,106.486654,29.615467,106.581515)+"米");
//        System.out.println(getDistance(-74.002166748,40.7520027161,-74.00182,40.751812)+"米");
//
//        List<Point> list = new ArrayList<>();
//        Point p1 = new Point(-74.09447350341799,40.94786487705935);
////        p1.getLng() = -74.09447350341799;
////        p1.getLat() = 40.94786487705935;
//
//        list.add(p1);
//        Point p2 = new Point(-73.89053978759767,40.945531011466265);
////        p1.getLng() = -73.89053978759767;
////        p1.getLat() = 40.945531011466265;
//        list.add(p2);
//
//        Point p3 = new Point(-73.88218696369324,40.59321408874445);
//
////        p3.getLng() = -73.88218696369324;
////        p3.getLat() = 40.59321408874445;
//        list.add(p3);
//
//        Point p4 = new Point(-74.09413018066408,40.59321408874445);
////        p4.getLng() = -74.09413018066408;
////        p4.getLat() = 40.59321408874445;
//        list.add(p4);
//
//        Point p = new Point(-73.99182,40.768696);
////        p.getLng() = -73.99182;
////        p.getLat() = 40.768696;
//
//        System.err.println(isPolygonContainsPoint(list, new Point(-79.985306,36.167164)));
//    }

    /**
     * 返回一个点是否在一个多边形区域内
     *
     * @param mPoints 多边形坐标点列表
     * @param point   待判断点
     * @return true 多边形包含这个点,false 多边形未包含这个点。
     */
    public static boolean isPolygonContainsPoint(List<Point> mPoints, Point point) {
        int nCross = 0;
        for (int i = 0; i < mPoints.size(); i++) {
            Point p1 = mPoints.get(i);
            Point p2 = mPoints.get((i + 1) % mPoints.size());
            // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
            // p1p2是水平线段,要么没有交点,要么有无限个交点
            if (p1.getLat() == p2.getLat())
                continue;
            // point 在p1p2 底部 --> 无交点
            if (point.getLat() < Math.min(p1.getLat(), p2.getLat()))
                continue;
            // point 在p1p2 顶部 --> 无交点
            if (point.getLat() >= Math.max(p1.getLat(), p2.getLat()))
                continue;
            // 求解 point点水平线与当前p1p2边的交点的 X 坐标
            double x = (point.getLat() - p1.getLat()) * (p2.getLng() - p1.getLng()) / (p2.getLat() - p1.getLat()) + p1.getLng();
            if (x > point.getLng()) // 当x=point.x时,说明point在p1p2线段上
                nCross++; // 只统计单边交点
        }
        // 单边交点为偶数，点在多边形之外 ---
        return (nCross % 2 == 1);
    }

    /**
     * 返回一个点是否在一个多边形边界上
     *
     * @param mPoints 多边形坐标点列表
     * @param point   待判断点
     * @return true 点在多边形边上,false 点不在多边形边上。
     */
    public static boolean isPointInPolygonBoundary(List<Point> mPoints, Point point) {
        for (int i = 0; i < mPoints.size(); i++) {
            Point p1 = mPoints.get(i);
            Point p2 = mPoints.get((i + 1) % mPoints.size());
            // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数

            // point 在p1p2 底部 --> 无交点
            if (point.getLat() < Math.min(p1.getLat(), p2.getLat()))
                continue;
            // point 在p1p2 顶部 --> 无交点
            if (point.getLat() > Math.max(p1.getLat(), p2.getLat()))
                continue;

            // p1p2是水平线段,要么没有交点,要么有无限个交点
            if (p1.getLat() == p2.getLat()) {
                double minX = Math.min(p1.getLng(), p2.getLng());
                double maxX = Math.max(p1.getLng(), p2.getLng());
                // point在水平线段p1p2上,直接return true
                if ((point.getLat() == p1.getLat()) && (point.getLng() >= minX && point.getLng() <= maxX)) {
                    return true;
                }
            } else { // 求解交点
                double x = (point.getLat() - p1.getLat()) * (p2.getLng() - p1.getLng()) / (p2.getLat() - p1.getLat()) + p1.getLng();
                if (x == point.getLng()) // 当x=point.x时,说明point在p1p2线段上
                    return true;
            }
        }
        return false;
    }


}
